/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
 * Author: Huawei OS Kernel Lab
 * Create: Thu Aug 15 16:14:23 2023
 */

#ifndef __LIBLINUX_ASM_SPINLOCK_H
#define __LIBLINUX_ASM_SPINLOCK_H

#if defined(CONFIG_LIBLINUX_PREEMPT) && defined(CONFIG_LIBLINUX_CDC)
#include_next <asm/spinlock.h>
#else
#include <liblinux/pal.h>

#include <asm/processor.h>
#include <asm/spinlock_types.h>
#include <linux/compiler.h>

static inline void arch_spin_unlock_wait(arch_spinlock_t *lock)
{
	liblinux_pal_mutex_lock(lock);
	liblinux_pal_mutex_unlock(lock);
}

#define arch_spin_lock_flags(lock, flags) arch_spin_lock(lock)

static inline void arch_spin_lock(arch_spinlock_t *lock)
{
	liblinux_pal_mutex_lock(lock);
}

static inline int arch_spin_trylock(arch_spinlock_t *lock)
{
	return !liblinux_pal_mutex_trylock(lock);
}

static inline void arch_spin_unlock(arch_spinlock_t *lock)
{
	liblinux_pal_mutex_unlock(lock);
}

static inline int arch_spin_value_unlocked(arch_spinlock_t lock)
{
	int ret = liblinux_pal_mutex_trylock(&lock);
	if (ret == 0) {
		liblinux_pal_mutex_unlock(&lock);
		return 1;
	}
	return 0;
}

static inline int arch_spin_is_locked(arch_spinlock_t *lock)
{
	return liblinux_pal_mutex_is_locked(lock);
}

static inline int arch_spin_is_contended(arch_spinlock_t *lock)
{
	int ret = liblinux_pal_mutex_trylock(lock);
	if (ret == 0) {
		liblinux_pal_mutex_unlock(lock);
		return 0;
	}
	return 1;
}

#define arch_spin_is_contended	arch_spin_is_contended

static inline void arch_write_lock(arch_rwlock_t *lock)
{
	liblinux_pal_rwlock_wrlock(lock);
}

static inline int arch_write_trylock(arch_rwlock_t *lock)
{
	return !liblinux_pal_rwlock_trywrlock(lock);
}

static inline void arch_write_unlock(arch_rwlock_t *lock)
{
	liblinux_pal_rwlock_unlock(lock);
}

static inline void arch_read_lock(arch_rwlock_t *lock)
{
	liblinux_pal_rwlock_rdlock(lock);
}

static inline int arch_read_trylock(arch_rwlock_t *lock)
{
	return !liblinux_pal_rwlock_tryrdlock(lock);
}

static inline void arch_read_unlock(arch_rwlock_t *lock)
{
	liblinux_pal_rwlock_unlock(lock);
}

#define arch_read_lock_flags(lock, flags)  arch_read_lock(lock)
#define arch_write_lock_flags(lock, flags) arch_write_lock(lock)

#define arch_spin_relax(lock)  cpu_relax()
#define arch_read_relax(lock)  cpu_relax()
#define arch_write_relax(lock) cpu_relax()

#ifdef CONFIG_ARM64
#define smp_mb__before_spinlock() smp_mb()
#endif

#endif /* CONFIG_LIBLINUX_PREEMPT */
#endif /* __LIBLINUX_ASM_SPINLOCK_H */
